/* 
   19.1 navbar组件 新增固定定位
   19.2 实现本地聊天功能
   19.3 实现聊天功能 io  注意事项  弄成回调函数的更新方式去更新list
   19.4 聊天框滚动到最新的位置
   19.5 优化 不允许为空的发送信息 监听按下事件

*/

import Icon from '@/components/Icon';
import Input from '@/components/Input';
import NavBar from '@/components/NavBar';
import styles from './index.module.scss';
import { useState, useEffect, useRef } from 'react';
import io, { Socket } from 'socket.io-client';
import { baseURL } from '@/utils/request';
import { getToken } from '@/utils/storage';
import { Toast } from 'antd-mobile';

type MsgType = {
  type: string;
  msg: string;
  timestamp: number;
};

export default function Chat() {
  // 19.2.3 声明input 受控组件
  const [msg, setMsg] = useState('');
  // 19.2.1 声明聊天数组
  const [msgList, setMsgList] = useState<MsgType[]>([]);
  // 19.3.5 绑定ref 更改 client 为 clientRef.current
  const clientRef = useRef<Socket | null>(null);

  // 19.3.1  挂载后创建实例
  useEffect(() => {
    // 19.3.2 创建客户端实例
    clientRef.current = io(baseURL, {
      query: { token: getToken().token },
      transports: ['websocket'],
    });
    // 19.3.3 第一次连接成功后的回调
    clientRef.current.on('connect', () => {
      console.log('连接成功...');
      // 主动发送一条数据  只是为了渲染聊天框
      setMsgList([
        { msg: '很开心为你服务', type: 'robot', timestamp: Date.now() },
      ]);
    });

    // 19.3.7  监听接收服务端的消息 同时更新MsgList
    clientRef.current.on('message', (data) => {
      console.log('49,data', data);
      //同时更新MsgList
      //19.3.8 修改被覆盖的msgList setMsgList是异步的 解决办法 弄成回调函数的更新方式去更新list
      //  原 setMsgList([...msgList, { ...data, type: 'robot' }]);
      setMsgList((preList) => {
        return [...preList, { ...data, type: 'robot' }];
      });
    });

    // 19.3.4 卸载后关闭连接
    return () => {
      clientRef.current?.close();
    };
  }, []);

  // 19.4.1 监听msgList 的数据变化
  useEffect(() => {
    window.scrollTo({
      top: document.body.scrollHeight,
      behavior: 'smooth', //动画 过渡
    });
  }, [msgList]);

  // 19.2.6 发送按钮点击事件  handleSendMsg 添加到数组
  const handleSendMsg = () => {
    // 19.5.1 不允许发送空消息
    if (msg.trim()) {
      // 19.3.6 向服务端发送消息 ,同时更新msgList
      clientRef.current?.emit('message', {
        msg: msg,
        timestamp: Date.now(),
      });
      //同时更新msgList
      setMsgList([
        ...msgList,
        { type: 'user', msg: msg, timestamp: Date.now() },
      ]);
      //清空input
      setMsg('');
    } else {
      Toast.show({ content: '傻叉,不能发送空消息' });
    }
  };
  // 19.5.2 监听按下确定事件
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      handleSendMsg();
    }
  };

  return (
    <div className={styles.root}>
      {/* 顶部导航栏 */}
      <NavBar fixed>小智同学</NavBar>

      {/* 聊天记录列表 */}
      <div className="chat-list">
        {/* 机器人的消息 */}
        {/* 19.2.2 遍历聊天数组 */}
        {msgList.map((item) => {
          return item.type === 'robot' ? (
            <div className="chat-item" key={item.timestamp}>
              <Icon type="iconbtn_xiaozhitongxue" />
              <div className="message">{item.msg}</div>
            </div>
          ) : (
            <div className="chat-item user" key={item.timestamp}>
              <img
                src={'http://toutiao.itheima.net/images/user_head.jpg'}
                alt=""
              />
              <div className="message">{item.msg}</div>
            </div>
          );
        })}
      </div>

      <div className="footer">
        {/* 底部消息输入框 */}
        <div className="input-footer">
          {/* 19.2.4 绑定value onchange 受控组件 */}
          <Input
            className="no-border"
            placeholder="请描述您的问题"
            value={msg}
            onChange={(e) => setMsg(e.target.value)}
            onKeyDown={(e) => handleKeyDown(e)}
          />
          <Icon type="iconbianji" />
          {/* 19.2.5 发送按钮点击事件  handleSendMsg */}
          <span className="send" onClick={handleSendMsg}>
            发送
          </span>
        </div>
      </div>
    </div>
  );
}
